/*
 * Copyright 2008 Zoundry LLC, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 */
package org.zoundry.gaedt.ui.views;

import java.io.File;
import java.net.URL;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.browser.IWorkbenchBrowserSupport;
import org.eclipse.ui.forms.events.HyperlinkAdapter;
import org.eclipse.ui.forms.events.HyperlinkEvent;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Hyperlink;
import org.eclipse.ui.forms.widgets.Section;
import org.eclipse.ui.part.ViewPart;
import org.zoundry.gaedt.core.util.ZGaeUtil;
import org.zoundry.gaedt.sdk.IZGaeSDKObserver;
import org.zoundry.gaedt.sdk.ZGaeSDK;
import org.zoundry.gaedt.ui.ZGaeColorUtil;
import org.zoundry.gaedt.ui.views.actions.ZGaeCheckForUpdatesAction;


/**
 * The GAE SDK View.
 */
public class ZGaeSdkView extends ViewPart implements IZGaeSDKObserver
{
    /** The version of the SDK. */
    private Label mVersionLabel;
    /** The download location URL. */
    private Hyperlink mDownloadHyperlink;
    /** When the SDK was downloaded. */
    private Label mTimestampLabel;
    /** Where the SDK was installed to. */
    private Hyperlink mInstallLocationHyperlink;

    /**
     * The constructor.
     */
    public ZGaeSdkView()
    {
    }

    /**
     * This is a call-back that will allow us to create the viewer and
     * initialize it.
     *
     * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite)
     */
    @Override
    public void createPartControl(Composite aParent)
    {
        ScrolledComposite scrolledComposite = new ScrolledComposite(aParent, SWT.H_SCROLL
                | SWT.V_SCROLL);

        FormToolkit toolkit = new FormToolkit(Display.getCurrent());
        Color white = ZGaeColorUtil.white(toolkit);
        Color labelColor = ZGaeColorUtil.editorLabelForeground(toolkit);

        Composite composite = toolkit.createComposite(scrolledComposite);
        composite.setBackground(white);
        composite.setLayout(new GridLayout(1, false));
        GridData data = new GridData(GridData.FILL_BOTH);
        composite.setLayoutData(data);

        scrolledComposite.setContent(composite);
        scrolledComposite.setMinSize(500, 175);
        scrolledComposite.setExpandHorizontal(true);
        scrolledComposite.setExpandVertical(true);

        Section section = toolkit.createSection(composite, Section.TITLE_BAR);
        section.setText("Current SDK Information");
        data = new GridData(GridData.FILL_BOTH);
        section.setLayoutData(data);
        section.setLayout(new GridLayout(1, false));
        Label label = toolkit.createLabel(section, "Use this section to examine all of the details about the currently downloaded and installed version of the Google App Engine SDK.");
        section.setDescriptionControl(label);

        composite = toolkit.createComposite(section);
        composite.setBackground(white);
        composite.setLayout(new GridLayout(2, false));
        data = new GridData(GridData.FILL_BOTH);
        composite.setLayoutData(data);
        section.setClient(composite);

        // The SDK version
        label = toolkit.createLabel(composite, "SDK Version:");
        label.setForeground(labelColor);
        data = new GridData(GridData.VERTICAL_ALIGN_CENTER | GridData.HORIZONTAL_ALIGN_END);
        label.setLayoutData(data);

        mVersionLabel = toolkit.createLabel(composite, "");
        data = new GridData(GridData.VERTICAL_ALIGN_CENTER | GridData.HORIZONTAL_ALIGN_BEGINNING | GridData.FILL_HORIZONTAL);
        mVersionLabel.setLayoutData(data);

        // The Download location
        label = toolkit.createLabel(composite, "Downloaded From:");
        label.setForeground(labelColor);
        data = new GridData(GridData.VERTICAL_ALIGN_CENTER | GridData.HORIZONTAL_ALIGN_END);
        label.setLayoutData(data);

        mDownloadHyperlink = toolkit.createHyperlink(composite, "", 0);
        data = new GridData(GridData.VERTICAL_ALIGN_CENTER | GridData.HORIZONTAL_ALIGN_BEGINNING | GridData.FILL_HORIZONTAL);
        mDownloadHyperlink.setLayoutData(data);

        // The Download timestamp
        label = toolkit.createLabel(composite, "Downloaded On:");
        label.setForeground(labelColor);
        data = new GridData(GridData.VERTICAL_ALIGN_CENTER | GridData.HORIZONTAL_ALIGN_END);
        label.setLayoutData(data);

        mTimestampLabel = toolkit.createLabel(composite, "", 0);
        data = new GridData(GridData.VERTICAL_ALIGN_CENTER | GridData.HORIZONTAL_ALIGN_BEGINNING | GridData.FILL_HORIZONTAL);
        mTimestampLabel.setLayoutData(data);

        // The install location
        label = toolkit.createLabel(composite, "Installed To:");
        label.setForeground(labelColor);
        data = new GridData(GridData.VERTICAL_ALIGN_CENTER | GridData.HORIZONTAL_ALIGN_END);
        label.setLayoutData(data);

        mInstallLocationHyperlink = toolkit.createHyperlink(composite, "", 0);
        data = new GridData(GridData.VERTICAL_ALIGN_CENTER | GridData.HORIZONTAL_ALIGN_BEGINNING | GridData.FILL_HORIZONTAL);
        mInstallLocationHyperlink.setLayoutData(data);

        ZGaeSDK sdk = ZGaeSDK.getInstance();

        populateControls(sdk);
        createControlListeners();
        contributeToActionBars();

        sdk.addObserver(this);
    }

    /**
     * Populates the controls with the values from the SDK.
     */
    protected void populateControls(ZGaeSDK aSdk)
    {
        mVersionLabel.setText(aSdk.getVersion());
        mDownloadHyperlink.setText(aSdk.getDownloadLocation().toString());
        mDownloadHyperlink.setHref(aSdk.getDownloadLocation());
        mTimestampLabel.setText(formatTimestamp(aSdk.getTimestamp()));
        mInstallLocationHyperlink.setText(formatInstallLocation(aSdk.getLocation()));
        mInstallLocationHyperlink.setHref(aSdk.getLocation());
    }

    /**
     * Creates listeners for the hyperlink controls.
     */
    protected void createControlListeners()
    {
        mDownloadHyperlink.addHyperlinkListener(new HyperlinkAdapter()
        {
            /**
             * @see org.eclipse.ui.forms.events.HyperlinkAdapter#linkActivated(org.eclipse.ui.forms.events.HyperlinkEvent)
             */
            @Override
            public void linkActivated(HyperlinkEvent aEvent)
            {
                try
                {
                    IWorkbenchBrowserSupport browserSupport = PlatformUI.getWorkbench().getBrowserSupport();
                    browserSupport.getExternalBrowser().openURL((URL) aEvent.getHref());
                }
                catch (PartInitException e)
                {
                    ZGaeUtil.logAndDisplayError(e);
                }
            }
        });

        mInstallLocationHyperlink.addHyperlinkListener(new HyperlinkAdapter()
        {
            /**
             * @see org.eclipse.ui.forms.events.HyperlinkAdapter#linkActivated(org.eclipse.ui.forms.events.HyperlinkEvent)
             */
            @Override
            public void linkActivated(HyperlinkEvent aEvent)
            {
                try
                {
                    String location = (String) aEvent.getHref();
                    File file = new File(location);
                    URL url = file.toURL();
                    IWorkbenchBrowserSupport browserSupport = PlatformUI.getWorkbench().getBrowserSupport();
                    browserSupport.getExternalBrowser().openURL(url);
                }
                catch (Exception e)
                {
                    ZGaeUtil.logAndDisplayError(e);
                }
            }
        });
    }

    /**
     * Formats the given timestamp into something more readable.
     *
     * @param aTimestamp
     */
    protected String formatTimestamp(Date aTimestamp)
    {
        String dateStr = DateFormat.getDateInstance(DateFormat.LONG).format(aTimestamp);
        String timeStr = new SimpleDateFormat("h:mm a").format(aTimestamp);
        return dateStr + " (" + timeStr + ")";
    }

    /**
     * Formats the install location into something a little easier to read.
     *
     * @param aInstallLocation
     */
    protected String formatInstallLocation(String aInstallLocation)
    {
        IWorkspace workspace = ResourcesPlugin.getWorkspace();
        IPath workspaceRootPath = workspace.getRoot().getLocation();
        IPath installLocationPath = new Path(aInstallLocation);
        IPath relativeInstallLocPath = installLocationPath.removeFirstSegments(workspaceRootPath.segmentCount() - 1);
        relativeInstallLocPath = relativeInstallLocPath.setDevice(null);
        return relativeInstallLocPath.toPortableString();
    }

    /**
     * Passing the focus request to the viewer's control.
     */
    @Override
    public void setFocus()
    {
    }

    /**
     * Make contributions to the action bars.
     */
    private void contributeToActionBars()
    {
        IActionBars bars = getViewSite().getActionBars();
        fillLocalToolBar(bars.getToolBarManager());
        bars.updateActionBars();
    }

    /**
     * Make contributions to the tool bar.
     *
     * @param aManager
     */
    private void fillLocalToolBar(IToolBarManager aManager)
    {
        aManager.removeAll();
        aManager.add(getCheckForUpdatesAction());
    }

    /**
     * Creates and returns an action.
     */
    private IAction getCheckForUpdatesAction()
    {
        return new ZGaeCheckForUpdatesAction();
    }

    /**
     * @see org.zoundry.gaedt.sdk.IZGaeSDKObserver#update(org.zoundry.gaedt.sdk.ZGaeSDK)
     */
    public void update(final ZGaeSDK aSdk)
    {
        Display.getDefault().asyncExec(new Runnable()
        {
            public void run()
            {
                populateControls(aSdk);
            }
        });
    }
}
